package org.cleverframe.modules.sys.service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.cleverframe.common.service.BaseService;
import org.cleverframe.common.utils.LevelStringUtils;
import org.cleverframe.common.vo.AjaxMessage;
import org.cleverframe.modules.sys.SysBeanNames;
import org.cleverframe.modules.sys.dao.DictDao;
import org.cleverframe.modules.sys.dao.OrganizationDao;
import org.cleverframe.modules.sys.entity.Dict;
import org.cleverframe.modules.sys.entity.Organization;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

/**
 * 组织机构Service<br>
 * @author LiZW
 * @version 2015年6月26日 下午4:26:30
 */
@Service(SysBeanNames.OrganizationService)
public class OrganizationService extends BaseService
{
    /** “机构类型”的字典类型名 */
    public final static String ORG_TYPE_DICT ="机构类型";
    /** “机构类型层级规则”的字典类型名 */
    public final static String ORG_LEVEL_RULE = "机构类型层级规则";
    public final static String ROOT_ORG_TYPE = "顶级机构类型";
    public final static String GROUP_CHILD_ORG = "集团的直接子机构";
    public final static String AREA_CHILD_ORG = "区域的直接子机构";
    public final static String COMPANY_CHILD_ORG = "公司的直接子机构";
    public final static String DEPARTMENT_CHILD_ORG = "部门的直接子机构";
    public final static String TEAM_CHILD_ORG = "小组的直接子机构";
    
    @Autowired
    @Qualifier(SysBeanNames.OrganizationDao)
    private OrganizationDao organizationDao;

    @Autowired
    @Qualifier(SysBeanNames.DictDao)
    private DictDao dictDao;

    /**
     * 根据机构ID获取机构信息
     * @param id 机构ID
     * @return 机构对象
     */
    public Organization getOrganizationById(Serializable id)
    {
        return organizationDao.getHibernateDao().get(id);
    }

    /**
     * 查询所有机构对象
     */
    public List<Organization> findAllOrganization()
    {
        return organizationDao.findAllOrganization();
    }

    /**
     * 获取所有机构信息，排除当前机构以及当前机构的所有下级机构<br>
     */
    public List<Organization> getOrgTreeExcludeOneself(String fullPath)
    {
        return organizationDao.getOrgTreeExcludeOneself(fullPath);
    }

    /**
     * 查询机构的直接子机构的可选类型<br>
     * @param orgId 机构ID
     * @return 直接子机构可选类型的数据字典集合
     */
    public List<Dict> getChildOrgType(Long orgId)
    {
        List<Dict> dictList = new ArrayList<Dict>();
        Organization org = organizationDao.getHibernateDao().get(orgId);
        if (org == null || org.getOrgType() == null)
        {
            return dictList;
        }
        String childOrgType = null;
        childOrgType = getOrgLevelRuleDictKey(org.getOrgType());
        Dict dict = dictDao.getDictByTypeAndkey(ORG_LEVEL_RULE, childOrgType); // 获取"机构类型层级规则"
        if (dict == null || dict.getDictValue() == null)
        {
            return dictList;
        }
        String[] orgTypeArray = dict.getDictValue().split("\\|");
        for (String orgType : orgTypeArray)
        {
            Dict tmp = dictDao.getDictByTypeAndValue(ORG_TYPE_DICT, orgType);
            if (tmp != null)
            {
                dictList.add(tmp);
            }
        }
        return dictList;
    }
    
    /**
     * 根据机构类型值返回"机构类型层级规则"的字典名称
     * @param orgType 机构类型
     * @return "机构类型层级规则"的字典名称
     */
    private String getOrgLevelRuleDictKey(Character orgType)
    {
        String childOrgType = "";
        if (new Character(Organization.TYPE_GROUP).equals(orgType))
        {
            childOrgType = GROUP_CHILD_ORG;
        }
        else if (new Character(Organization.TYPE_AREA).equals(orgType))
        {
            childOrgType = AREA_CHILD_ORG;
        }
        else if (new Character(Organization.TYPE_COMPANY).equals(orgType))
        {
            childOrgType = COMPANY_CHILD_ORG;
        }
        else if (new Character(Organization.TYPE_DEPARTMENT).equals(orgType))
        {
            childOrgType = DEPARTMENT_CHILD_ORG;
        }
        else if (new Character(Organization.TYPE_TEAM).equals(orgType))
        {
            childOrgType = TEAM_CHILD_ORG;
        }
        else
        {
            return null;
        }
        return childOrgType;
    }
    
    
    /**
     * 保存机构对象，线程同步方法<br>
     * 1.机构类型层级规则，顶级机构、当前机构的下级机构类型、机构类型从数据字典中获取<br>
     *   a) 哪些机构类型可以是顶级机构(没有父机构的机构)<br>
     *   b) 每种机构的子机构可以有哪些类型的机构(如：部门下面只能有人员，不能有公司)<br>
     * 2.验证增加的机构的父机构是否合理<br>
     * 3.设置机构编码，此步骤需要使用同步<br>
     * 4.设置机构树结构的全路径<br>
     * 
     * @param org 机构对象
     * @param message 返回的结果消息
     */
    public synchronized boolean addOrganization(Organization org, AjaxMessage message)
    {
        /* ----------------------------------机构类型规则验证---------------------------------- */
        Organization parentOrg = null;
        String childOrgType = "";
        if (org.isRootOrg())
        {
            childOrgType = ROOT_ORG_TYPE;
        }
        else
        {
            parentOrg = organizationDao.getHibernateDao().get(org.getParentId());
            if (parentOrg == null)
            {
                
                message.setMessage("此机构[" + org.getName() + "]的父机构不存在");
                return false;
            }
            childOrgType = getOrgLevelRuleDictKey(parentOrg.getOrgType());
            if (StringUtils.isBlank(childOrgType))
            {
                message.setMessage("此机构[" + org.getName() + "]的父机构[" + parentOrg.getName() + "]的机构类型错误");
                return false;
            }
        }
        Dict dict = dictDao.getDictByTypeAndkey(ORG_LEVEL_RULE, childOrgType); // 获取"机构类型层级规则"
        if (dict == null)
        {
            message.setMessage("数据字典没有定义此机构[" + childOrgType + "]的“机构类型层级规则”");
            return false;
        }
        else
        {
            boolean flag = false;
            String[] orgTypeArray = dict.getDictValue().split("\\|");
            for (String type : orgTypeArray)
            {
                if (type.equals(org.getOrgType().toString()))
                {
                    flag = true;
                    break;
                }
            }
            if (false == flag)
            {
                message.setMessage("机构类型规则验证失败，请配置数据字典[type=" + ORG_LEVEL_RULE + ",key=" + childOrgType + "]");
                return false;
            }
        }
        
        /* ----------------------------------保存机构---------------------------------- */
        if (org.isRootOrg())
        {
            org.setParentId(-1L);
        }
        
        //设置机构编码code，如：001002007008
        String code = organizationDao.getMaxCode(org.getParentId());
        if (StringUtils.isBlank(code))
        {
            if (parentOrg == null)
            {
                // 保存的节点是第一个根节点
                code = LevelStringUtils.rootLevelString(Organization.CODE_LEVEL_LENGTH);
            }
            else
            {
                // 保存的节点是第一个节点，但不是根节点
                code = parentOrg.getCode() + LevelStringUtils.rootLevelString(Organization.CODE_LEVEL_LENGTH);
            }
        }
        else
        {
            // 保存的节点既不是第一个节点，也不是根节点
            code = LevelStringUtils.nextLevelString(Organization.CODE_LEVEL_LENGTH, code);
        }
        org.setCode(code);
        organizationDao.getHibernateDao().save(org);
        // 更新full_path属性，Hibernate会自动更新
        if (org.isRootOrg())
        {
            org.setFullPath(org.getId().toString());
        }
        else
        {
            org.setFullPath(parentOrg.getFullPath() + Organization.FULL_PATH_SPLIT + org.getId());
        }
        return true;
    }
    
    /**
     * 更新机构对象，线程同步方法<br>
     * 1.不能修改：parent_id、full_path、code、org_type<br>
     * 
     * @param org 机构对象
     */
    public boolean updateOrganization(Organization org, AjaxMessage message)
    {
        /* ----------------------------------验证是否修改了不能修改的字段---------------------------------- */
        Organization oldOrg = organizationDao.getHibernateDao().get(org.getId());
        if (oldOrg == null)
        {
            message.setMessage("此机构[ID=" + org.getId() + "]不存在");
            return false;
        }
        if(!oldOrg.getParentId().equals(org.getParentId()))
        {
            message.setMessage("不能修改机构的上级机构");
            return false; 
        }
        if(!oldOrg.getFullPath().equals(org.getFullPath()))
        {
            message.setMessage("不能修改机构的层级关系");
            return false; 
        }
        if(!oldOrg.getCode().equals(org.getCode()))
        {
            message.setMessage("不能修改机构编码");
            return false; 
        }
        if(!oldOrg.getOrgType().equals(org.getOrgType()))
        {
            // TODO 机构没有子机构就可以修改机构类型？
            message.setMessage("不能修改机构类型");
            return false; 
        }
        /* ----------------------------------更新数据---------------------------------- */
        organizationDao.getHibernateDao().getSession().evict(oldOrg);
        organizationDao.getHibernateDao().update(org);
        return true;
    }

    /**
     * 删除机构<br>
     * 1.只能软删除一个空机构(该机构下没有任何其他机构和人员)<br>
     */
    public boolean deleteOrg(Organization org, AjaxMessage message)
    {
        Organization oldArea = organizationDao.getHibernateDao().get(org.getId());
        if (oldArea == null)
        {
            message.setSuccessUrl("删除机构失败，机构不存在，机构ID：" + org.getId());
            return false;
        }
        /* -----------------验证该机构是否有子机构----------------- */
        int count = organizationDao.getChildrenOrgCount(oldArea.getId());
        if (count > 0)
        {
            message.setSuccessUrl("不能删除一个有子机构的机构，此机构的子机构数量：" + count);
            return false;
        }
        /* -----------------验证该机构下是否有人员----------------- */
        // TODO 验证该机构下是否有人员
        
        /* -----------------软删除机构----------------- */
        organizationDao.getHibernateDao().deleteById(oldArea.getId());
        return true;
    }

    /**
     * 获取组织架构中的所有公司<br>
     * @return 公司集合
     */
    public List<Organization> getAllCompany()
    {
        return organizationDao.getAllCompany();
    }

    /**
     * 获取某公司的所有机构(包括该公司)<br>
     * @param companyId 公司ID
     * @return 某公司下的所有机构集合
     */
    public List<Organization> getOrgByCompany(Long companyId)
    {
        if (companyId == null)
        {
            return new ArrayList<Organization>();
        }
        Organization company = organizationDao.getHibernateDao().get(companyId);
        if (company == null 
            || (company.getOrgType() != Organization.TYPE_GROUP && company.getOrgType() != Organization.TYPE_COMPANY) 
            || StringUtils.isBlank(company.getFullPath()))
        {
            return new ArrayList<Organization>();
        }
        return organizationDao.getChildrenOrg(company.getFullPath() + "%");
    }
}
